home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------------------------------------
-
- 3D2 to Raytracer File Converter
- Copyright (c) 1992 by Steve Anger
-
- Converts files from Cyber Sculpt 3D2 format (Atari) to POV-Ray or Vivid
- raytracer formats. This file may be freely modified and distributed.
-
- CompuServe: 70714,3113
- YCCMR BBS: (708)358-5611
-
- --------------------------------------------------------------------------*/
-
- #define __GNUC__
-
- #ifndef __GNUC__
- #include <alloc.h>
- #endif
-
- #include <stdio.h>
- #include <portab.h>
- #include <stdlib.h>
- #include <string.h>
- #include <math.h>
-
-
- #include "rayopt.h"
-
-
-
- #ifdef __TURBOC__
- extern unsigned _stklen = 16384;
- #endif
-
- #define VERSION "v1.8"
-
- #define ASPECT 1.333
-
- #define POV10 0
- #define POV20 1
- #define VIVID 2
- #define RAW 99
-
- typedef struct
- {
- float x, y, z;
- } Vector;
-
-
- typedef struct
- {
- int x, y, z;
- } IVector;
-
-
- typedef struct
- {
- float red;
- float green;
- float blue;
- } Palette;
-
-
- typedef struct
- {
- int vert_a; /* Vertex A of the triangle */
- int vert_b; /* " B " " " */
- int vert_c; /* " C " " " */
- int colour; /* Colour of triangle */
- } Triangle;
-
-
- typedef unsigned char byte;
- typedef signed int word;
-
-
- /* Function prototype definitions */
- void process_args (int argc, char *argv[]);
- byte read_byte (FILE *f);
- word read_word (FILE *f);
- void read_3d2_header (void);
- void convert_object (void);
- void write_intro (void);
- void write_triangle (Vector a, Vector b, Vector c, Palette pal);
- void write_summary (void);
- void write_light (Vector pos, float red, float green, float blue);
- void write_camera (Vector pos, Vector target, float lens);
- char upcase (char c);
- void fswap (float *a, float *b);
-
- /* Global variables */
- FILE *in; /* Input file */
- FILE *out; /* Output file */
- char infile[64]; /* Input file name */
- char outfile[64]; /* Output file name */
- Vector look_at; /* Location to look at */
- Vector view_point; /* Location of view_point */
- int verbose; /* Verbose messages flag */
- int format; /* Output format */
- float smooth; /* Smooth triangles who's normals differ by */
- /* less than this angle (degrees) */
-
- /* 3D2 Header infomation */
- int obj_count; /* Number of objects contained in file */
- int light_on[3]; /* 1 = Light source is on, 0 = off */
- float light_bright[3]; /* Light source brightness */
- Vector light_pos[3]; /* Light source position */
- Palette pal[16]; /* Colour palette for objects */
-
- /* 3D2 Object information */
- char obj_name[12]; /* Name of current object */
- int vert_count; /* Number of vertices in object */
- IVector *vert; /* Pointer to array of vertices */
- int tri_count; /* Number of triangular faces in object */
- int degen_count; /* Degenerate triangles */
-
-
-
- int main (int argc, char* argv[])
- {
- int i, total_vert, total_tri, total_degen, total_bounds;
-
- process_args (argc, argv);
-
- if (format != RAW) {
- opt_set_format (format);
- opt_set_quiet (!verbose);
- opt_set_smooth (smooth);
- opt_set_dec (2);
- opt_set_fname (outfile, "");
- }
-
- in = fopen (infile, "rb");
- if (in == NULL)
- abortmsg ("Error opening input file.", 1);
-
- out = fopen (outfile, "w");
- if (out == NULL)
- abortmsg ("Error opening output file.", 1);
-
- total_vert = 0;
- total_tri = 0;
- total_degen = 0;
- total_bounds = 0;
-
- read_3d2_header();
- write_intro();
-
- printf (" Object Vertices Triangles Degen Tri Bounds Bnd Index\n");
- printf ("---------- ----------- ----------- ----------- -------- -----------\n");
-
- for (i = 0; i < obj_count; i++) {
- convert_object();
-
- printf (" %6d %6d %6d %6d %8.2f\n",
- vert_count, tri_count, degen_count,
- opt_get_bounds(), opt_get_index());
-
- total_vert += vert_count;
- total_tri += tri_count;
- total_degen += degen_count;
- total_bounds += opt_get_bounds();
- }
-
- write_summary(); /* Finish off the file */
-
- printf (" =========== =========== =========== ========\n");
- printf (" Totals %6d %6d %6d %6d\n",
- total_vert, total_tri, total_degen, total_bounds);
-
- printf ("\nConverted %d object(s), ", obj_count);
- printf ("%d light source(s).\n\n", light_on[0] + light_on[1] + light_on[2]);
-
- fclose(in);
- fclose(out);
-
- return 0;
- }
-
- void process_args (int argc, char *argv[])
- {
- int i;
-
- printf ("\n");
- printf ("3D2 to POV-Ray/Vivid Converter %s, ", VERSION);
- printf ("Copyright (c) 1993 Steve Anger\n");
- #if defined(__GNUC__) && defined(i386)
- printf ("32 bit version. DOS Extender Copyright (c) 1991 DJ Delorie\n");
- #endif
- printf ("This program is freely distributable\n\n");
-
- if (argc < 2) {
- printf ("Usage: 3d2-pov inputfile[.3d2] [outputfile] [options]\n\n");
- printf ("Options: -lxnnn - Set look_at x coord to nnn\n");
- printf (" -lynnn - ' ' y ' ' ' \n");
- printf (" -lznnn - ' ' z ' ' ' \n");
- printf (" -vxnnn - Set view_point x coord to nnn\n");
- printf (" -vynnn - ' ' y ' ' ' \n");
- printf (" -vznnn - ' ' z ' ' ' \n");
- printf (" -snnn - Smooth triangle boundaries with angles < nnn\n");
- printf (" -op - Output to POV-Ray 1.0 format (default)\n");
- printf (" -op2 - Output to POV-Ray 2.0 format\n");
- printf (" -ov - Output to Vivid 2.0 format\n");
- printf (" -or - Output to RAW triangle format\n");
- printf ("\n e.g. 3d2-pov car.3d2 car.pov -s60.0\n\n");
- exit(1);
- }
-
- strcpy (infile, "");
- strcpy (outfile, "");
-
- smooth = 60.0;
- verbose = 0;
- format = POV10;
-
- view_point.x = +50.0;
- view_point.y = -50.0;
- view_point.z = +50.0;
-
- look_at.x = 0.0;
- look_at.y = 0.0;
- look_at.z = 0.0;
-
- for (i = 1; i < argc; i++) {
- if (argv[i][0] == '-' || argv[i][0] == '/') {
- switch (upcase(argv[i][1])) {
- case 'S': if (argv[i][2] == '\0')
- smooth = 60.0;
- else
- sscanf (&argv[i][2], "%f", &smooth);
- break;
-
- case 'L': switch (upcase(argv[i][2])) {
- case 'X': sscanf (&argv[i][3], "%f", &look_at.x);
- break;
- case 'Y': sscanf (&argv[i][3], "%f", &look_at.y);
- break;
- case 'Z': sscanf (&argv[i][3], "%f", &look_at.z);
- }
- break;
-
- case 'V': switch (upcase(argv[i][2])) {
- case 'X': sscanf (&argv[i][3], "%f", &view_point.x);
- break;
- case 'Y': sscanf (&argv[i][3], "%f", &view_point.y);
- break;
- case 'Z': sscanf (&argv[i][3], "%f", &view_point.z);
- }
- break;
-
- case 'O': switch (upcase(argv[i][2])) {
- case 'P': if (argv[i][3] == '2')
- format = POV20;
- else
- format = POV10;
- break;
-
- case 'V': format = VIVID;
- break;
-
- case 'R': format = RAW;
- break;
- }
- break;
-
- default: printf ("Invalid option -%c, ignored.\n\n", argv[i][1]);
- }
- }
- else if (strlen(infile) == 0) {
- strcpy (infile, argv[i]);
- add_ext (infile, "3d2", 0);
- }
- else if (strlen (outfile) == 0) {
- strcpy (outfile, argv[i]);
-
- switch (format) {
- case POV10:
- case POV20: add_ext (outfile, "pov", 0); break;
- case VIVID: add_ext (outfile, "v", 0); break;
- case RAW: add_ext (outfile, "raw", 0); break;
- }
- }
- else
- abortmsg ("Too many file names", 1);
- }
-
- if (strlen (infile) == 0)
- abortmsg ("No input file specified", 1);
-
- /* Prevent a division by zero error later on */
- if ((view_point.x - look_at.x) == 0.0 && (view_point.z - look_at.z) == 0.0)
- view_point.z -= 0.01;
-
- if (strlen (outfile) == 0) {
- strcpy (outfile, infile);
-
- switch (format) {
- case POV10:
- case POV20: add_ext (outfile, "pov", 1); break;
- case VIVID: add_ext (outfile, "v", 1); break;
- case RAW: add_ext (outfile, "raw", 1); break;
- }
- }
-
- if (format == POV10 || format == POV20)
- fswap (&view_point.y, &view_point.z);
- }
-
-
- byte read_byte (FILE *f)
- {
- return fgetc(f);
- }
-
-
- word read_word (FILE *f)
- {
- byte bh, bl;
- word res;
-
- bh = fgetc(f);
- bl = fgetc(f);
-
- res = 256*bh + bl;
-
- /* A sign adjustment for non-16 bit machines. */
- if (sizeof(word) > 2 && (res & 0x8000) != 0)
- res = ((-1) << 16) | res;
-
- return (res);
- }
-
-
- void read_3d2_header()
- {
- int i;
- word temp;
-
- if (read_word(in) != 0x3D02)
- abortmsg ("Input file is not 3D2 format.", 1);
-
- obj_count = read_word(in);
-
- light_on[0] = read_word(in);
- light_on[1] = read_word(in);
- light_on[2] = read_word(in);
-
- light_bright[0] = read_word(in)/7.0;
- light_bright[1] = read_word(in)/7.0;
- light_bright[2] = read_word(in)/7.0;
-
- read_word(in); /* Skip the ambient light level */
-
- light_pos[0].z = (float)read_word(in);
- light_pos[1].z = (float)read_word(in);
- light_pos[2].z = (float)read_word(in);
-
- light_pos[0].y = (float)read_word(in);
- light_pos[1].y = (float)read_word(in);
- light_pos[2].y = (float)read_word(in);
-
- light_pos[0].x = (float)read_word(in);
- light_pos[1].x = (float)read_word(in);
- light_pos[2].x = (float)read_word(in);
-
- if (format == POV10 || format == POV20) {
- fswap (&light_pos[0].y, &light_pos[0].z);
- fswap (&light_pos[1].y, &light_pos[1].z);
- fswap (&light_pos[2].y, &light_pos[2].z);
- }
-
- for (i = 0; i < 16; i++) {
- temp = read_word(in);
- pal[i].red = ((temp & 0x0700) >> 8)/7.0;
- pal[i].green = ((temp & 0x0070) >> 4)/7.0;
- pal[i].blue = (temp & 0x0007)/7.0;
- }
-
- for (i = 0; i < 188; i++)
- read_byte(in);
- }
-
-
- void convert_object()
- {
- int i, va, vb, vc, col;
- Vector a, b, c;
-
- for (i = 0; i < 9; i++)
- obj_name[i] = read_byte(in);
-
- cleanup_name (obj_name);
-
- printf (" %-8s", obj_name);
- fflush (stdout);
-
- if (format == RAW)
- fprintf (out, "%s\n", obj_name);
-
- vert_count = read_word(in);
-
- if (vert_count > 0) {
- vert = malloc (vert_count * sizeof(*vert));
- if (vert == NULL)
- abortmsg ("Insufficient memory for vertices.", 1);
- }
-
- for (i = 0; i < vert_count; i++) {
- vert[i].x = read_word(in);
- vert[i].y = read_word(in);
- vert[i].z = read_word(in);
- }
-
- /* Tell optimizer how many vertices to expect */
- if (format != RAW)
- opt_set_vert (vert_count);
-
- tri_count = read_word(in);
- degen_count = 0;
-
- for (i = 0; i < tri_count; i++) {
- va = read_word(in);
- vb = read_word(in);
- vc = read_word(in);
- read_byte(in);
- col = read_byte(in);
-
- a.x = vert[va].x / 100.0;
- a.y = vert[va].y / 100.0;
- a.z = vert[va].z / 100.0;
-
- b.x = vert[vb].x / 100.0;
- b.y = vert[vb].y / 100.0;
- b.z = vert[vb].z / 100.0;
-
- c.x = vert[vc].x / 100.0;
- c.y = vert[vc].y / 100.0;
- c.z = vert[vc].z / 100.0;
-
- if (format == POV10 || format == POV20) {
- fswap (&a.y, &a.z);
- fswap (&b.y, &b.z);
- fswap (&c.y, &c.z);
- }
-
- write_triangle (a, b, c, pal[col]);
- }
-
- if (vert_count > 0)
- free (vert);
-
- if (format != RAW) {
- fclose(out);
- opt_write_file (obj_name);
- out = fopen (outfile, "a");
- }
- }
-
-
-
- void write_intro()
- {
- switch (format) {
- case POV10:
- case POV20:
- fprintf (out, "/* Converted from file %s with 3D2-POV %s */\n\n",
- infile, VERSION);
- fprintf (out, "#include \"colors.inc\"\n");
- fprintf (out, "#include \"textures.inc\"\n\n");
- break;
-
- case VIVID:
- fprintf (out, "/* Converted from file %s with 3D2-POV %s */\n\n",
- infile, VERSION);
- fprintf (out, "#include color.vc\n\n");
- break;
- }
- }
-
-
- void write_triangle (Vector a, Vector b, Vector c, Palette pal)
- {
- switch (format) {
- case POV10:
- case POV20:
- case VIVID:
- opt_set_color (pal.red, pal.green, pal.blue);
-
- if (opt_add_tri (a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z) < 0)
- ++degen_count;
-
- break;
-
- case RAW:
- fprintf (out, "%.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f %.2f\n",
- a.x, a.y, a.z, b.x, b.y, b.z, c.x, c.y, c.z);
- break;
- }
- }
-
-
- void write_summary()
- {
- int i;
-
- switch (format) {
- case POV10:
- case POV20:
- case VIVID:
- fclose(out);
- opt_finish();
- out = fopen (outfile, "a");
-
- for (i = 0; i < 3; i++) {
- if (light_on[i])
- write_light (light_pos[i], light_bright[i], light_bright[i], light_bright[i]);
- }
-
- write_camera (view_point, look_at, 35.0);
- break;
- }
- }
-
-
- void write_light (Vector pos, float red, float green, float blue)
- {
- switch (format) {
- case POV10:
- fprintf (out, "object {\n");
- fprintf (out, " light_source { <%.4f %.4f %.4f> color red %4.2f green %4.2f blue %4.2f }\n",
- pos.x, pos.y, pos.z, red, green, blue);
- fprintf (out, "}\n\n");
- break;
-
- case POV20:
- fprintf (out, "light_source {\n");
- fprintf (out, " <%.4f, %.4f, %.4f> color red %4.2f green %4.2f blue %4.2f\n",
- pos.x, pos.y, pos.z, red, green, blue);
- fprintf (out, "}\n\n");
- break;
-
- case VIVID:
- fprintf (out, "light {\n");
- fprintf (out, " type point\n");
- fprintf (out, " position %.4f %.4f %.4f\n",
- pos.x, pos.y, pos.z);
- fprintf (out, " color %4.2f %4.2f %4.2f\n",
- red, green, blue);
- fprintf (out, "}\n\n");
- break;
- }
- }
-
-
- void write_camera (Vector pos, Vector target, float lens)
- {
- switch (format) {
- case POV10:
- fprintf (out, "camera {\n");
- fprintf (out, " location <%.4f %.4f %.4f>\n",
- pos.x, pos.y, pos.z);
- fprintf (out, " direction <0 0 %.2f>\n", lens/35.0);
- fprintf (out, " up <0 1 0>\n");
- fprintf (out, " sky <0 1 0>\n");
- fprintf (out, " right <%.3f 0 0>\n", ASPECT);
- fprintf (out, " look_at <%.4f %.4f %.4f>\n",
- target.x, target.y, target.z);
- fprintf (out, "}\n\n");
- break;
-
- case POV20:
- fprintf (out, "camera {\n");
- fprintf (out, " location <%.4f, %.4f, %.4f>\n",
- pos.x, pos.y, pos.z);
- fprintf (out, " direction <0, 0, %.2f>\n", lens/35.0);
- fprintf (out, " up <0, 1, 0>\n");
- fprintf (out, " sky <0, 1, 0>\n");
- fprintf (out, " right <%.3f, 0, 0>\n", ASPECT);
- fprintf (out, " look_at <%.4f, %.4f, %.4f>\n",
- target.x, target.y, target.z);
- fprintf (out, "}\n\n");
- break;
-
- case VIVID:
- fprintf (out, "studio {\n");
- fprintf (out, " from %.4f %.4f %.4f\n", pos.x, pos.y, pos.z);
- fprintf (out, " at %.4f %.4f %.4f\n",
- target.x, target.y, target.z);
- fprintf (out, " up 0 0 1\n");
- fprintf (out, " angle %.2f\n",
- 2.0 * (180.0/M_PI) * atan (35.0/lens) / ASPECT);
- fprintf (out, " aspect %.3f\n", ASPECT);
- fprintf (out, " resolution 320 200\n");
- fprintf (out, " antialias none\n");
- fprintf (out, "}\n\n");
- break;
- }
- }
-
-
- char upcase (char c)
- {
- if (c >= 'a' && c <= 'z')
- c = c - 'a' + 'A';
-
- return c;
- }
-
-
- void fswap (float *a, float *b)
- {
- float temp;
-
- temp = *a;
- *a = *b;
- *b = temp;
- }
-